package com.david.core.imgloader;

import android.annotation.SuppressLint;
import android.app.Application;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ImageDownLoader {
    private static Context applicationContext;

    private static ImageDownLoader instance;

    /**kotlin协程对于并行下载多个任务并不适合，所以在此使用线程池*/
    private ExecutorService executorService;

    public interface OnImageDownLoadListener{
        void onImageDownLoad(String filePath);
        void onImageDownLoadError(String error, String url);
    }

    @SuppressLint("HandlerLeak")
    private final Handler mHandler = new Handler();

    public static ImageDownLoader getInstance() {
        if (instance == null) {
            synchronized (ImageDownLoader.class) {
                if (instance == null) {
                    instance = new ImageDownLoader();
                }
            }
        }
        return instance;
    }

    public void init(Application applicationContext) {
        if (ImageDownLoader.applicationContext == null) {
            ImageDownLoader.applicationContext = applicationContext;
            executorService = Executors.newFixedThreadPool(10);
        }
    }

    private ImageDownLoader() {
    }

    public void downloadImage( String url, OnImageDownLoadListener imageDownLoadListener) {

//        downloadImage(url,applicationContext.getExternalCacheDir().getAbsolutePath() + "/" +System.currentTimeMillis()+".jpg", imageDownLoadListener);
        /*app私有目录不需要权限即可访问*/
        downloadImage(url,applicationContext.getExternalFilesDir(Environment.DIRECTORY_PICTURES).getAbsolutePath() + "/" +System.currentTimeMillis()+".jpg", imageDownLoadListener);
        /*需要权限访问sd卡*/
//        downloadImage(url, Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + "/" +System.currentTimeMillis()+".jpg", imageDownLoadListener);
    }

        /**
         * 下载图片任务
         */
    public void downloadImage(String url, String outPath, OnImageDownLoadListener imageDownLoadListener) {
        String imageID = getImageName(url);
        executorService.execute(new DownLoadTask(url, imageID, outPath, imageDownLoadListener, mHandler));
    }

    private static class DownLoadTask implements Runnable {
        private String url;
        private String imageID;
        private String outPath;
        private OnImageDownLoadListener imageDownLoadListener;
        private Handler mHandler;

        public DownLoadTask(String url, String imageID, String outPath, OnImageDownLoadListener imageDownLoadListener, Handler handler) {
            this.url = url;
            this.imageID = imageID;
            this.outPath = outPath;
            this.imageDownLoadListener = imageDownLoadListener;
            this.mHandler = handler;
        }

        @Override
        public void run() {
            InputStream is = null;
            try {
                //创建一个url对象
                URL rawUrl = new URL(url);
                //设置超时时间
                HttpURLConnection urlConn = (HttpURLConnection) rawUrl.openConnection();
                urlConn.setConnectTimeout(5000);
                urlConn.setReadTimeout(5000);
                urlConn.setUseCaches(true);
                urlConn.connect();
                int code = urlConn.getResponseCode();
                if (code != 200) {
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            if (imageDownLoadListener != null) {
                                imageDownLoadListener.onImageDownLoadError("download error code:" + code, url);
                            }
                        }
                    });
                    return;
                }

                //打开URL对应的资源输入流
                is = urlConn.getInputStream();



                /*开始解析图片*/
                Bitmap bitmap;
                if (urlConn.getContentLength() > 300000) {//大于300k的先存文件,在从处理图片文件
                    writeToFile(is, outPath);
                    bitmap = loadImage(imageID);
                } else {//小于300k直接获取bitmap并存储
                    byte[] byteArray = getBytesInputStream(is);

                    bitmap = loadImage(byteArray);
                    //                        writeToFile(byteArray, filePath);
                }
                compressWrite(bitmap, outPath);

                /*解析图片完成*/

                //关闭输入流
                is.close();

                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        if (imageDownLoadListener != null) {
                            imageDownLoadListener.onImageDownLoad(outPath);
                        }
                    }
                });


            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (is != null) {
                    try {
                        is.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                imageDownLoadListener = null;
                url = null;
                imageID = null;
                outPath = null;
                mHandler = null;
            }
        }
    };

    private static byte[] getBytesInputStream(InputStream is) throws IOException {
        ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
        byte[] buff = new byte[512];
        int len;
        while ((len = is.read(buff)) != -1) {
            arrayOutputStream.write(buff, 0, len);
        }
        is.close();
        arrayOutputStream.close();
        return arrayOutputStream.toByteArray();
    }


    /**从缓存文件中加载图片*/
    private static Bitmap loadImage(String imageID){
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(applicationContext.getExternalCacheDir() + File.separator + imageID, options);

//        options.inSampleSize = width > 0?options.outWidth / width:2;//默认缩小一倍
        options.inJustDecodeBounds = false;
        options.inPreferredConfig = Bitmap.Config.RGB_565;

        return BitmapFactory.decodeFile(applicationContext.getExternalCacheDir() + File.separator + imageID, options);
    }

    /**从缓存文件中加载图片*/
    private Bitmap loadImage(String imageID, int width){
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(applicationContext.getExternalCacheDir() + File.separator + imageID, options);

        options.inSampleSize = width > 0?options.outWidth / width:2;//默认缩小一倍
        options.inJustDecodeBounds = false;
        options.inPreferredConfig = Bitmap.Config.RGB_565;

        return BitmapFactory.decodeFile(applicationContext.getExternalCacheDir() + File.separator + imageID, options);
    }

    /**从二进制数组中加载图片*/
    private static Bitmap loadImage(byte[] array){
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeByteArray(array, 0, array.length,  options);

//        options.inSampleSize = width > 0?options.outWidth / width:2;//默认缩小一倍
        options.inJustDecodeBounds = false;
        options.inPreferredConfig = Bitmap.Config.RGB_565;

        return BitmapFactory.decodeByteArray(array, 0, array.length,  options);
    }

    /**从二进制数组中加载图片*/
    private Bitmap loadImage(byte[] array, int width){
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeByteArray(array, 0, array.length,  options);

        options.inSampleSize = width > 0?options.outWidth / width:2;//默认缩小一倍
        options.inJustDecodeBounds = false;
        options.inPreferredConfig = Bitmap.Config.RGB_565;

        return BitmapFactory.decodeByteArray(array, 0, array.length,  options);
    }


    /**小图时加载到内存并保存*/
    private void writeToFile(byte[] data, String fileAbsolutePath) {
        FileOutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(fileAbsolutePath);
            outputStream.write(data, 0, data.length);
            outputStream.flush();

            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /**图片大于300k时先写入文件，防止图片很大导致oom*/
    private static void writeToFile(InputStream is, String fileAbsolutePath) {
        BufferedInputStream bufferedInputStream = null;
        FileOutputStream fileOutputStream = null;
        BufferedOutputStream bufferedOutputStream = null;
        try {

            bufferedInputStream = new BufferedInputStream(is);
            fileOutputStream = new FileOutputStream(fileAbsolutePath);
            bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
            byte[] buff = new byte[512];
            int len;
            while ((len = bufferedInputStream.read(buff)) != -1) {
                bufferedOutputStream.write(buff, 0, len);
            }
        } catch (IOException e){
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (bufferedInputStream != null) {
                try {
                    bufferedInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bufferedOutputStream != null) {
                try {
                    bufferedOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static void compressWrite(Bitmap bitmap, String outFilePath){
        try {
            FileOutputStream saveImgOut = new FileOutputStream(outFilePath);
            // compress - 压缩的意思
            bitmap.compress(Bitmap.CompressFormat.JPEG, 70, saveImgOut);
            //存储完成后需要清除相关的进程
            saveImgOut.flush();
            saveImgOut.close();
            Log.d("Save Bitmap", "The picture is save to your phone!");
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }


    /**
     * 获取带后缀的图片名
     * https://pics2.baidu.com/feed/d043ad4bd11373f07cfedf093f1d9bfcfaed0479.jpeg?token=de18eb3030df73681a7ee453fb698651&s=95A742B60A9168CEE4BF9D7A03009018
     * https://img-home.csdnimg.cn/images/20201231031228.jpg
     *
     * @param imageUrl 图片url
     * @return 带后缀的图片名
     */
    private String getImageName(String imageUrl) {
        if (imageUrl.contains("?")) {//带参数
            imageUrl = imageUrl.substring(0, imageUrl.indexOf("?"));
        }
        return imageUrl.substring(imageUrl.lastIndexOf("/") + 1);
    }
}
